package freaks.terah.gui;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

import freaks.terah.model.Data;
import freaks.terah.model.EnvironmentModel;
import freaks.terah.model.FileIO;
import freaks.terah.model.Observer;
import freaks.terah.model.PlayerModel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

public class NewMainFrame extends JPanel implements Observer {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	Gui guiParent;
	PlayerModel theModel;
	JPanel frame;
	private JTextField actionField;
	private RessourceCountPanel allRessources;
	private JLabel lblCurrentTurn;
	private MissionFrame missionPanel;
	private RessourceFrame resFrame;
	private EnvironmentModel theEnvironment;
	/**
	 * Create the panel.
	 */
	public NewMainFrame(Gui aParent) {
		setLayout(null);
		frame = this;
		PlayerModel model = new PlayerModel(0,0,0,0);
		EnvironmentModel env = new EnvironmentModel();
		theModel = model;
		theEnvironment = env;
		//JButton btnNewButton = new JButton("New button");
		//btnNewButton.setBounds(279, 233, 117, 29);
		//add(btnNewButton);
		
		JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		tabbedPane.setBounds(13, 53, 739, 570);
		add(tabbedPane);
		
		missionPanel = new MissionFrame(model, aParent);
		tabbedPane.addTab("Mission", null, missionPanel, null);
		
		JPanel technologyPanel = new TechnologyFrame(model);
		tabbedPane.addTab("Technology", null, technologyPanel, null);
		
		JPanel ressourcePanel = new StructureFrame(model);
		tabbedPane.addTab("Structures", null, ressourcePanel, null);
		
		JPanel unitPanel = new UnitFrame(model);
		tabbedPane.addTab("Units", null, unitPanel, null);
		
		JButton btnEndTurn = new JButton("End Turn");
		btnEndTurn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				int option = 0;
				if (theModel.getCurrentAP() != 0)
				{
					String message = "You can still do " + theModel.getCurrentAP() + " action(s). Are you sure you want to end your turn?";
					option = JOptionPane.showConfirmDialog(frame, message, "End Turn", JOptionPane.YES_NO_OPTION);
				} else {
					option = JOptionPane.showConfirmDialog(frame, "Are you sure you want to end your turn?", "End Turn", JOptionPane.YES_NO_OPTION);
				}
				
				if (option == JOptionPane.OK_OPTION)
				{
					if (resFrame.isNetPositive())
					{
						theModel.doPostTurn();
					    saveDataToFile(missionPanel.getServerData());
					    
					    System.exit(0);
					}
					
					JOptionPane.showMessageDialog(frame, "You can't end your turn with a negative balance. Turn some structures off and/or destroy some units to fix this.", "Unbalanced Ship!", JOptionPane.WARNING_MESSAGE);
				}
			}
		});
		btnEndTurn.setBounds(585, 624, 117, 29);
		add(btnEndTurn);
		theModel.addListener(this);
		
		allRessources = new RessourceCountPanel(RessourceCountPanel.HORIZONTAL_LAYOUT, true);
		allRessources.setBounds(197, 16, 330, 32);
		add(allRessources);
		
		JLabel lblRessources = new JLabel("Ressources:");
		lblRessources.setBounds(110, 25, 75, 16);
		add(lblRessources);
		
		actionField = new JTextField();
		actionField.setHorizontalAlignment(SwingConstants.CENTER);
		actionField.setBounds(68, 20, 30, 28);
		add(actionField);
		actionField.setEnabled(false);
		actionField.setEditable(false);
		actionField.setColumns(10);
		
		JLabel lblActions = new JLabel("Actions:");
		lblActions.setBounds(13, 25, 61, 16);
		add(lblActions);
		
		lblCurrentTurn = new JLabel("Current Turn: ");
		lblCurrentTurn.setBounds(566, 25, 122, 16);
		add(lblCurrentTurn);
		guiParent = aParent;
		
		notifyMe();
	}
	
	protected void saveDataToFile(Data[] datas) {
		guiParent.setTurn(guiParent.getTurn()+1);
		Data[] globals = guiParent.getGlobalData(theModel);
		Data[] ressources = theModel.getAllPlayerRessources();
		
		int totalData = globals.length + ressources.length;
		
		Data[] saveData = new Data[totalData];
		for (int i = 0; i < globals.length; i++)
			saveData[i] = globals[i];
		for (int i = 0; i < ressources.length; i++)
			saveData[i + globals.length] = ressources[i];
		
		try {
			FileIO io = new FileIO();
			String fileData = io.encode(saveData);
			String encryptedData = String.valueOf(guiParent.getID()) + "," + String.valueOf(guiParent.getTurn()) + "," +
			                       String.valueOf(theModel.getPlayerNumber()) + "," + io.encrypt(fileData, guiParent.getID() + guiParent.getTurn(), theModel.getPlayerNumber());
			String encryptedServerData = io.encrypt(io.encode(datas), guiParent.getID() + guiParent.getTurn() , theModel.getPlayerNumber());
			
			if (theModel.getRole() == 2)
			{
				encryptedData += ","  + io.encrypt(io.encode(theEnvironment.getPlanetData()),guiParent.getID() + guiParent.getTurn(), theModel.getPlayerNumber());
			}
			
			io.saveFile(frame, null, encryptedData, encryptedServerData, theModel.getRole());
		    if (theModel.getRole() == 1)
		    {
		    	JOptionPane.showInputDialog(frame, "Here's the server code. It's also saved in ServerCode.txt, in the same folder your save file is in.", "Server Code", JOptionPane.PLAIN_MESSAGE, null, null, encryptedServerData);
		    }
		    	
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void setInitData(String data, String serverData) throws Exception {
		FileIO io = new FileIO();
		String[] stuff = data.split(",");
		Data[] gameData = io.decode(io.decrypt(stuff[3], Integer.parseInt(stuff[0]) + Integer.parseInt(stuff[1]), Integer.parseInt(stuff[2])));
	
		guiParent.setID(Integer.parseInt(gameData[0].getData()));
		guiParent.setTurn(Integer.parseInt(gameData[2].getData()));
		lblCurrentTurn.setText(lblCurrentTurn.getText() + gameData[2].getData());

		int playerNums = Integer.parseInt(gameData[3].getData());
		
		guiParent.getPlayers().clear();
		for (int i = 0; i < playerNums; i++)
			guiParent.getPlayers().addElement(gameData[4 + i].getData());
		

		theModel.setRole(Integer.parseInt(gameData[1].getData()));
		theModel.setPlayerNumber(Integer.parseInt(gameData[4 + playerNums].getData()));
		theModel.setGoal(Integer.parseInt(gameData[5 + playerNums].getData()));
		theModel.setShip(Integer.parseInt(gameData[6 + playerNums].getData()));
		
		theModel.setAllPlayerRessources(gameData, 7 + playerNums);
		
		if (theModel.getRole() == 2 && guiParent.getTurn() != 1)
	    {
	    	int len2;
		    char[] chr2 = new char[4096];
		    final StringBuffer buffer2 = new StringBuffer();
		    final FileReader reader2 = new FileReader(new File("clientCodes.txt"));
		    try {
		        while ((len2 = reader2.read(chr2)) > 0) {
		            buffer2.append(chr2, 0, len2);
                }
		    } finally {
		        reader2.close();
		    }
		    
		    ArrayList<Data[]> clientCodes = new ArrayList<Data[]>();
		    clientCodes.add(io.decode(io.decrypt(stuff[5], Integer.parseInt(stuff[0]) + Integer.parseInt(stuff[1]), Integer.parseInt(stuff[2]))));
		    
		    String[] stuff2 = buffer2.toString().split(",");
		    
		    for (int i = 0; i < guiParent.getPlayers().getSize()-1;i++)
		    	clientCodes.add(io.decode(io.decrypt(stuff2[i],Integer.parseInt(stuff[0]) + Integer.parseInt(stuff[1]), i+2)));
		    
		    theEnvironment.setPlanetData(io.decode(io.decrypt(stuff[4], Integer.parseInt(stuff[0]) + Integer.parseInt(stuff[1]), Integer.parseInt(stuff[2]))));
		    
		    ArrayList<Data[]> playerRessources = theEnvironment.doServerStuff(clientCodes, guiParent.getTurn());
		    
		    serverData = generateCodes(playerRessources);
	    }
		
		Data[] decodedServerData = io.decodeServerData(io.decrypt(serverData, Integer.parseInt(stuff[0]) + Integer.parseInt(stuff[1]), Integer.parseInt(stuff[2])));
		
		theEnvironment.generatePlanetData(guiParent.getTurn());
		
		missionPanel.setServerData(decodedServerData);
		
		resFrame = new RessourceFrame(theModel);
		resFrame.setLocationRelativeTo(this);
		resFrame.setLocation(this.getWidth(), this.getHeight()/2);
		resFrame.setVisible(true);
	}
	
	private String generateCodes(ArrayList<Data[]> clientData) throws Exception
	{
		FileIO io = new FileIO();
		String fileString = "Server codes\n-------------\n";

		for (int i = 1; i < guiParent.getPlayers().getSize(); i++)
		{
			String clientString = io.encrypt(io.encodeServerData(clientData.get(i)), guiParent.getID() + guiParent.getTurn(), i+1);
			fileString += (String) guiParent.getPlayers().get(i) + ": " + clientString + "\n";
		}
		
		fileString += "------------";
		
		File file = new File("serverString.txt");
		
		FileOutputStream stream = new FileOutputStream(file);
		stream.write(fileString.getBytes());
		stream.close();
		
		return io.encrypt(io.encodeServerData(clientData.get(0)), guiParent.getID() + guiParent.getTurn(), 1);
	}

	@Override
	public void notifyMe() {
		allRessources.setRessource(theModel.getPlayerRessources(), null);
		actionField.setText(Integer.toString(theModel.getCurrentAP()));
	}
}
